<?php

global $CFG;

require_once($CFG->libdir. '/simpletestlib/unit_tester.php');
require_once($CFG->libdir. '/simpletestlib/mock_objects.php');
require_once($CFG->libdir. '/simpletestlib.php');

require_once(dirname(__FILE__).'/../../../module_resourcepage.php');

class smb_fake {
    function get($archivepath,$filepath) {
        file_put_contents($filepath,$archivepath);        
    }
} 

class etexts_test extends UnitTestCase {
    
    private $module;
    private $beforeprefix;
    
    private $etexts;
    
    const TESTPREFIX='unittest_';
    const TESTPREFIXORA='t_';
    
    private function getTestPrefix() {
        global $CFG;
        if (isset($CFG->dbfamily) && ($CFG->dbfamily == 'oracle')) {
            return self::TESTPREFIXORA;
        }
        return self::TESTPREFIX;
    }

    function setUp() {
        global $CFG;
        
        // Set $CFG prefix for testing
        $this->beforeprefix=$CFG->prefix;
        $CFG->prefix=$this->getTestPrefix();

        $null=null;
        
        // Stuff that should've been cleaned up at end, but just in case
        $this->tearDown();
        
        // Set $CFG prefix for testing
        $CFG->prefix=$this->getTestPrefix();

        $this->module=new module_resourcepage();
        $this->etexts=$this->module->get_specified_extension('etexts');
        
        $this->install();
    }
    
    private function install() {
        global $CFG;        

        $mod = 'resourcepage';
        $fullmod = $CFG->dirroot .'/mod/'. $mod;
        $status = false;
        if (file_exists($fullmod . '/db/install.xml')) {
            ob_start();
            $status = install_from_xmldb_file($fullmod . '/db/install.xml');
            $this->module->create_extensions_list();
            ob_end_clean();
        }
        $this->assertTrue($status, 'Resourcepage module installation');
    }

    function tearDown() {
        global $CFG, $db;

        wipe_tables($this->getTestPrefix(), $db);
        wipe_sequences($this->getTestPrefix(), $db);

        @fulldelete($CFG->dataroot.'/unittest');

        // Put prefix back
        $CFG->prefix=$this->beforeprefix;
    }
    
    function files($names) {
        $return=array();
        foreach($names as $name) {
            $item=new stdClass;
            $item->filename=$name;
            $item->parentfolder='/test/'.count($return).'/';
            $return[]=$item;
            unset($item);
        }
        return $return;
    }
    
    function check_table($testcase,$rs,$write=false) {
        $result='';
        while(!$rs->EOF) {
            $first=true;
            foreach($rs->fields as $f) {
                if($first) {
                    $first=false;
                } else {
                    $result.="\t";
                }
                $result.=$f;
            }
            $result.="\n";
            $rs->MoveNext();
        }    
            
        if($write) { // Save test examples for later comparison        
            global $CFG;
            file_put_contents($CFG->dataroot.'/'.$testcase,$result);
        }
        
        $this->assertEqual($result,file_get_contents(dirname(__FILE__).'/'.$testcase));
    }
    
    function check_items_table($testcase,$write=false) {
        $this->check_table($testcase,
            $this->etexts->do_sql('SELECT itemid,publiccode,edition,currentimpression '.
                'FROM extprefix_items ORDER BY itemid'),$write);
    }
    
    function check_archive_table($testcase,$write=false) {
        $this->check_table($testcase,
            $this->etexts->do_sql('SELECT publiccode,edition,impression,filepath,archivepath '.
            'FROM extprefix_archv ORDER BY archivepath'),$write);
    }
    
    function check_relatedfiles_table($testcase,$write=false) {
        $this->check_table($testcase,$this->etexts->do_sql(<<<ENDQUERY
SELECT 
    xi.id,f.filepath,f.mimetype,f."size"
FROM 
    modprefix_items xi
    LEFT OUTER JOIN modprefix_files f ON xi.id=f.itemid
ORDER BY
    xi.id,f.filepath
ENDQUERY
            ),$write);
    }
    
     
    function test_update_archive_table() {
        // Add files matching a selection of conditions...
        $files=$this->files(array(
            'invalid a.pdf', // Should not be added
            'sup a SUP111111_v1-1_.pdf',
            'sup b SUP 111112_v1-1_.pdf',
            'sup c sup111113_v1-1_.pdf',
            'sup d s111114_v1-1_.pdf',
            'isbn a ISBN111111111X_v1-1_.pdf',
            'isbn b ISBN 111111112X_v1-1_.pdf',
            'isbn c isbn111111113X_v1-1_.pdf',
            'isbn d ISBN978111111111X_v1-1_.pdf',
            'version a SUP123456_v1-2_.pdf',
            'version b SUP123456_v13_.pdf',
            'version c SUP123456_v101_.pdf',
            'version d SUP123456_v10-20_.pdf',
            'duplicate a SUP111111_v1-1_.pdf', // Should not be added
            'wordformat a SUP111111_v1-1_.doc'
            ));
        $this->etexts->update_archive_table($files);
        $this->check_archive_table('archive1.testcase');

        // When data has not changed, should be no change to table either...        
        $this->etexts->update_archive_table($files);
        $this->check_archive_table('archive1.testcase');

        // Test delete
        $files=$this->files(array(
            'invalid a.pdf', // Should not be added
            'sup a SUP111111_v1-1_.pdf',
            'sup b SUP 111112_v1-1_.pdf',
            'sup c sup111113_v1-1_.pdf',
            'wordformat a SUP111111_v1-1_.doc' // To test keeping one of a pair 
            ));
        $this->etexts->update_archive_table($files);
        $this->check_archive_table('archive2.testcase');

        // Test rename
        $files=$this->files(array(
            'invalid a.pdf', // Should not be added
            'rename sup a SUP111111_v1-1_.pdf',
            'sup b SUP 111112_v1-1_.pdf',
            'sup c sup111113_v1-1_.pdf',
            'wordformat a SUP111111_v1-1_.doc' // To test keeping one of a pair 
            ));
        $this->etexts->update_archive_table($files);
        $this->check_archive_table('archive3.testcase');

        // Test add, delete, and rename
        $files=$this->files(array(
            'rename back sup a SUP111111_v1-1_.pdf',
            'sup b SUP 111112_v1-1_.pdf',
            'sup e sup111119_v1-1_.pdf',
            'wordformat a SUP111111_v1-1_.doc' // To test keeping one of a pair 
            ));
        $this->etexts->update_archive_table($files);
        $this->check_archive_table('archive4.testcase');

    }
     
    public function test_update_actual_files() {
        global $db;
        // Initialise tables
        $this->module->do_sql("INSERT INTO modprefix_items(title) VALUES('test 1')");
        $this->module->do_sql("INSERT INTO modprefix_items(title) VALUES('test 2')");
        $this->module->do_sql("INSERT INTO modprefix_items(title) VALUES('test 3')");
        $this->module->do_sql("INSERT INTO modprefix_items(title) VALUES('test 4')");
        $i1=1; $i2=2; $i3=3; $i4=4;
        $this->module->do_sql("INSERT INTO modprefix_items(basedonitemid,title) VALUES($i4,'test 5')");       
        $this->module->do_sql("INSERT INTO modprefix_items(basedonitemid,title) VALUES($i4,'test 6')");
        $this->module->do_sql("INSERT INTO modprefix_items(basedonitemid,title) VALUES($i2,'test 7')");
        $i5=5;$i6=6;$i7=7;
        
        $n1='unittest/etexts/test1 ignore same.pdf';
        $this->module->do_sql("INSERT INTO modprefix_files VALUES($i1,'".addslashes('unittest/etexts/test1 ignore same.pdf')."',' ',0)");
        $this->module->do_sql("INSERT INTO modprefix_files VALUES($i1,'test1.doc',' ',0)");
        $this->module->do_sql("INSERT INTO modprefix_files VALUES($i2,'test2 should go.pdf',' ',0)");
        $this->module->do_sql("INSERT INTO modprefix_files VALUES($i3,'test3.pdf',' ',0)");
        $this->module->do_sql("INSERT INTO modprefix_files VALUES($i5,'deleteme.doc',' ',0)");
        $this->module->do_sql("INSERT INTO modprefix_files VALUES($i6,'butnotme.pdf',' ',0)");
        $this->module->do_sql("INSERT INTO modprefix_files VALUES($i7,'orme.pdf',' ',0)");
            
        load_test_data($this->getTestPrefix().'resourcepage_x_etexts_items',array(
            array('itemid','publiccode','edition','currentimpression'),
            array($i1,'SUP000001',4,2),
            array($i2,'SUP000002',4,2),
            array($i3,'SUP000003',1,2),
            array($i4,'SUP000004',1,NULL),
            ),$db);
            
        load_test_data($this->getTestPrefix().'resourcepage_x_etexts_archv',array(
            array('publiccode','edition','impression','archivepath','filepath'),
            array('SUP000001',4,2,' ',$n1),
            // Also ignore the missing one from test1
            array('SUP000002',4,3,' ',$y1='unittest/etexts/test2 update impression.pdf'),
            array('SUP000003',4,2,' ',$n2='unittest/etexts/test3 ignore new edition.doc'),
            array('SUP000002',4,2,' ',$n3='unittest/etexts/test2 ignore old impression.doc'),
            array('SUP000002',4,3,' ',$y2='unittest/etexts/test2 additional file.doc'),
            array('SUP000004',4,2,' ',$n4='unittest/etexts/test4 ignore new edition.doc'),
            array('SUP000004',1,3,' ',$y3='unittest/etexts/test4 set up impression.doc')
            ),$db);
            
        $fake=new smb_fake();
        $this->etexts->update_actual_files($fake);
        
        // File copy checks
        global $CFG;
        $this->assertTrue(file_exists($CFG->dataroot.'/'.$y1));
        $this->assertTrue(file_exists($CFG->dataroot.'/'.$y2));
        $this->assertTrue(file_exists($CFG->dataroot.'/'.$y3));
        $this->assertFalse(file_exists($CFG->dataroot.'/'.$n1));
        $this->assertFalse(file_exists($CFG->dataroot.'/'.$n2));
        $this->assertFalse(file_exists($CFG->dataroot.'/'.$n3));
        $this->assertFalse(file_exists($CFG->dataroot.'/'.$n4));
        
        // DB table validity checks (against previously hand-verified data)
        $this->check_items_table('files1i.testcase',false);
        $this->check_relatedfiles_table('files2f.testcase',true);        
    }
}
?>
